﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Entity;
using System.Data.Entity.Validation;
using Simple.Common.Core.Log;
using System.Data.Entity.Infrastructure;
using Simple.Common.Data;
using System.Web;
using Simple.Entity;
using System.Reflection;
using System.Data.Entity.ModelConfiguration;
using Simple.Entity.Models;

namespace Simple.EF
{
    public class EfDbContext : DbContext
    {
        static EfDbContext()
        {
            Database.SetInitializer<EfDbContext>(null);
        }

        public EfDbContext()
        {
        }

        public override int SaveChanges()
        {
            try
            {
                ApplyChange();
                return base.SaveChanges();
            }
            catch (DbEntityValidationException dbEx)
            {
                var msg = string.Empty;

                foreach (var validationErrors in dbEx.EntityValidationErrors)
                    foreach (var validationError in validationErrors.ValidationErrors)
                        msg += string.Format("Property: {0} Error: {1}", validationError.PropertyName, validationError.ErrorMessage) + Environment.NewLine;

                SimpleLogHelper.Error("EF提交异常：" + msg, dbEx);
                var fail = new Exception(msg, dbEx);
                throw fail;
            }
        }

        protected virtual void ApplyChange()
        {
            foreach (var entry in ChangeTracker.Entries())
            {
                switch (entry.State)
                {
                    case EntityState.Added:
                        SetCreationAuditProperties(entry);
                        break;
                    case EntityState.Modified:
                        SetModificationAuditProperties(entry);
                        break;
                    case EntityState.Deleted:
                        SetSoftDelete(entry);
                        break;
                }
            }
        }

        protected virtual void SetCreationAuditProperties(DbEntityEntry entry)
        {
            if (entry.Entity is ICreation)
            {
                var creationEntity = entry.Cast<ICreation>().Entity;
                if (!string.IsNullOrEmpty(HttpContext.Current.User.Identity.Name))
                    creationEntity.CreateUser = HttpContext.Current.User.Identity.Name;
                creationEntity.CreateTime = DateTime.Now;
            }
        }

        protected virtual void SetModificationAuditProperties(DbEntityEntry entry)
        {
            if (entry.Entity is IModification)
            {
                var auditedEntry = entry.Cast<IModification>();

                auditedEntry.Entity.ModifyTime = DateTime.Now;
                if (!string.IsNullOrEmpty(HttpContext.Current.User.Identity.Name))
                    auditedEntry.Entity.ModifyUser = HttpContext.Current.User.Identity.Name;
            }
        }

        protected virtual void SetSoftDelete(DbEntityEntry entry)
        {
            if (entry.Entity is ISoftDelete)
            {
                var softDeleteEntry = entry.Cast<ISoftDelete>();
                softDeleteEntry.State = EntityState.Unchanged;
                softDeleteEntry.Entity.DeletedTime = DateTime.Now;
                if (!string.IsNullOrEmpty(HttpContext.Current.User.Identity.Name))
                    softDeleteEntry.Entity.DeletedUser = HttpContext.Current.User.Identity.Name;
                softDeleteEntry.Entity.IsDeleted = true;
            }
        }

    }
}
